/*!
    \copyright  Copyright (c) 2020 - 2025 Qualcomm Technologies International, Ltd.
            All Rights Reserved.
            Qualcomm Technologies International, Ltd. Confidential and Proprietary.
    \ingroup qualcomm_connection_manager
    \brief
*/

#ifdef INCLUDE_QCOM_CON_MANAGER

#include <message.h>
#include <task_list.h>
#include <panic.h>
#include <vm.h>
#include <logging.h>
#include <vsdm_prim.h>
#include "connection_manager.h"
#include "connection_manager_event_send.h"

#include "system_state.h"
#include "bt_device_class.h"

#include "qualcomm_connection_manager.h"
#include "qualcomm_connection_manager_private.h"


#ifndef HOSTED_TEST_ENVIRONMENT

/*! \brief There is checking that the messages assigned by this module do
not overrun into the next module's message ID allocation */
ASSERT_MESSAGE_GROUP_NOT_OVERFLOWED(QCOM_CON_MANAGER, QCOM_CON_MANAGER_MESSAGE_END)

#endif

/*! \brief Make the type used for message IDs available in debug tools */
LOGGING_PRESERVE_MESSAGE_TYPE(qcm_msgs_t)
LOGGING_PRESERVE_MESSAGE_TYPE(qualcomm_connection_manager_internal_message_t)

/*! \brief Control connection priority - 0x00 indicates low priority and 0xFF indicates high priority. */
#define QCOM_CON_MANGER_CONTROL_CONNECTION_PRIORITY_HIGH    (0xFF)
#define QCOM_CON_MANGER_CONTROL_CONNECTION_PRIORITY_LOW     (0x00)

/*! \brief Set PA data context info */
typedef struct
{
    QCOM_CON_MANAGER_SET_PA_DATA_REQ_T  pa_data;         /* PA data req */
    uint16                              next_data_index; /* Next data index of the PA data fragment */
} QCOM_CON_MANAGER_SET_PA_DATA_CONTEXT_T;

static Task client_truncated_scan = NULL;
static QcomConManagerVsdmPrimObserver vsdm_prim_observer;
#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE
static QCOM_CON_MANAGER_SET_PA_DATA_CONTEXT_T set_pa_data_context;
#endif /* INCLUDE_LE_AUDIO_BROADCAST_SOURCE */

static bool qcomConManagerIsQhsSupported(const uint8 *features)
{
    return ((features[QHS_MODE_2345_OCTET] & QHS_MODE_2345_MASK) ||
            (features[QHS_MODE_6_OCTET]    & QHS_MODE_6_MASK));
}

static bool qcomConManagerIsQhsSupportedForIsochronous(const uint8 *features)
{
    return (features[QHS_MODE_ISO_OCTET] & QHS_MODE_ISO_MASK);
}


static bool qcomConManagerIsFastExitSubrateSupported(const uint8 *features)
{
    return ((features[FAST_EXIT_SNIFF_SUBRATE_OCTET] & FAST_EXIT_SNIFF_SUBRATE_MASK) != 0);
}

static void qcomConManagerSendQhsConnectedIndicationToClients(const bdaddr *bd_addr)
{
    qcomConManagerTaskData *sp = QcomConManagerGet();
    MESSAGE_MAKE(qhs_connected_ind, QCOM_CON_MANAGER_QHS_CONNECTED_T);
    qhs_connected_ind->bd_addr = *bd_addr;
    TaskList_MessageSend(&sp->client_tasks, QCOM_CON_MANAGER_QHS_CONNECTED, qhs_connected_ind);
}

static void qcomConManagerSendRemoteQhsCapableIndicationToClients(const tp_bdaddr *tp_addr)
{
    qcomConManagerTaskData *sp = QcomConManagerGet();
    MESSAGE_MAKE(qhs_capable_ind, QCOM_CON_MANAGER_REMOTE_ISO_QHS_CAPABLE_IND_T);
    qhs_capable_ind->tp_addr = *tp_addr;
    TaskList_MessageSend(&sp->client_tasks, QCOM_CON_MANAGER_REMOTE_ISO_QHS_CAPABLE_IND, qhs_capable_ind);
}

static void qcomConManagerSendReadRemoteQlmSuppFeaturesReq(const BD_ADDR_T *bd_addr)
{
    MAKE_VSDM_PRIM_T(VSDM_READ_REMOTE_QLM_SUPP_FEATURES_REQ);
    prim->phandle = 0;
    prim->bd_addr = *bd_addr;
    VmSendVsdmPrim(prim);
}

static void qcomConManagerSendReadRemoteQllSuppFeaturesReq(const TP_BD_ADDR_T *tp_bd_addr)
{
    MAKE_VSDM_PRIM_T(VSDM_READ_REMOTE_QLL_SUPP_FEATURES_REQ);
    prim->phandle = 0;
    prim->tp_addrt = *tp_bd_addr;
    VmSendVsdmPrim(prim);
}

static void qcomConManagerTriggerRemoteFeaturesRead(const BD_ADDR_T *bd_addr, uint32 delay_ms)
{
    MESSAGE_MAKE(msg, QCOM_CON_MANAGER_INTERNAL_READ_QLM_REMOTE_FEATURES_T);
    msg->bd_addr = *bd_addr;
    MessageCancelFirst(QcomConManagerGetTask(), QCOM_CON_MANAGER_INTERNAL_READ_QLM_REMOTE_FEATURES);
    MessageSendLater(QcomConManagerGetTask(), QCOM_CON_MANAGER_INTERNAL_READ_QLM_REMOTE_FEATURES, msg, delay_ms);
}

static void qcomConManagerQllTriggerRemoteFeaturesRead(const TP_BD_ADDR_T *tp_addr, uint32 delay_ms)
{
    MESSAGE_MAKE(msg, QCOM_CON_MANAGER_INTERNAL_READ_QLL_REMOTE_FEATURES_T);
    msg->tp_addr = *tp_addr;
    MessageCancelFirst(QcomConManagerGetTask(), QCOM_CON_MANAGER_INTERNAL_READ_QLL_REMOTE_FEATURES);
    MessageSendLater(QcomConManagerGetTask(), QCOM_CON_MANAGER_INTERNAL_READ_QLL_REMOTE_FEATURES, msg, delay_ms);
}

static void qcomConManagerHandleVsdmQlmPhyChangeInd(const VSDM_QCM_PHY_CHANGE_IND_T * ind)
{
    DEBUG_LOG("qcomConManagerHandleVsdmQlmPhyChangeInd  qhs status=%d bdaddr lap=%06lX",
              ind->status,ind->bd_addr.lap);

    if(ind->status == HCI_SUCCESS)
    {
        bdaddr bd_addr;
        BdaddrConvertBluestackToVm(&bd_addr, &ind->bd_addr);
        qcomConManagerTriggerRemoteFeaturesRead(&ind->bd_addr, D_IMMEDIATE);
        ConManagerSetQhsConnectStatus(&bd_addr,TRUE);
        appDeviceSetQhsConnected(&bd_addr, TRUE);
        qcomConManagerSendQhsConnectedIndicationToClients(&bd_addr);
    }
}

static void qcomConManagerHandleVsdmSetWbmFeatureCfm(const VSDM_SET_WBM_FEATURES_CFM_T *cfm)
{
    DEBUG_LOG("qcomConManagerHandleVsdmSetWbmFeatureCfm status=%d", cfm->status);
}

static void qcomConManagerHandleVsdmRemoteQlmSuppFeaturesCfm(const VSDM_READ_REMOTE_QLM_SUPP_FEATURES_CFM_T *cfm)
{
    bool qhs_supported = FALSE;
    bool fast_exit_subrate_supported = FALSE;
    bdaddr bd_addr;

    BdaddrConvertBluestackToVm(&bd_addr, &cfm->bd_addr);

    /* Check if qhs is supported or not */
    if (cfm->status == HCI_SUCCESS)
    {
        qhs_supported = qcomConManagerIsQhsSupported(cfm->qlmp_supp_features);
        fast_exit_subrate_supported = qcomConManagerIsFastExitSubrateSupported(cfm->qlmp_supp_features);

        if (!qhs_supported)
        {
            /* Device doesn't support QHS, so clear the flag */
            appDeviceSetQhsConnected(&bd_addr, FALSE);
        }

    }

    DEBUG_LOG("qcomConManagerHandleVsdmRemoteQlmSuppFeaturesCfm status=%d lap:%x qhs:%d fes:%d",
               cfm->status, bd_addr.lap, qhs_supported, fast_exit_subrate_supported);

    ConManagerSetQhsSupportStatus(&bd_addr, qhs_supported);
    ConManagerSetFastExitSniffSubrateSupportStatus(&bd_addr, fast_exit_subrate_supported);
}


static void qcomConManagerHandleVsdmRemoteQllSuppFeaturesCfm(const VSDM_READ_REMOTE_QLL_SUPP_FEATURES_CFM_T *cfm)
{
    tp_bdaddr tp_addr;

    BdaddrConvertTpBluestackToVm(&tp_addr, &cfm->tp_addrt);
    DEBUG_LOG("qcomConManagerHandleVsdmRemoteQllSuppFeaturesCfm status=%d lap:%x",
               cfm->status, tp_addr.taddr.addr.lap);

    if (cfm->status == HCI_SUCCESS)
    {
        /* Check if QHS is supported or not */
        if (qcomConManagerIsQhsSupportedForIsochronous(cfm->qll_supp_features))
        {
            qcomConManagerSendRemoteQhsCapableIndicationToClients(&tp_addr);
        }
    }
}

#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE
static void qcomConManagerSendSetPADataReq(QCOM_CON_MANAGER_SET_PA_DATA_CONTEXT_T *pa_data_ctx)
{
    uint8 data_ptrs_index = 0;
    uint8 offset, length = 0;
    /* Create VSDM_LE_SET_PERIODIC_ADVERTISING_DATA_REQ */
    MAKE_VSDM_PRIM_T(VSDM_LE_SET_PERIODIC_ADVERTISING_DATA_REQ);

    prim->phandle = 0;
    prim->adv_handle = pa_data_ctx->pa_data.adv_handle;
    prim->anchor_point = pa_data_ctx->pa_data.anchor_point_us;
    prim->time_to_sync_point = pa_data_ctx->pa_data.time_to_sync_point_ms;
    prim->offset_in_adv_data = pa_data_ctx->pa_data.offset_for_time_info;

    prim->adv_data_len = pa_data_ctx->pa_data.size - pa_data_ctx->next_data_index;
    if (pa_data_ctx->next_data_index == 0)
    {
        prim->operation =
                prim->adv_data_len <= VSDM_PERIODIC_ADV_DATA_LENGTH ? QCOM_CON_MANGER_PA_FRAGMENT_TYPE_COMPLETE :
                                                                      QCOM_CON_MANGER_PA_FRAGMENT_TYPE_FIRST;
    }
    else
    {
        prim->operation =
                prim->adv_data_len <= VSDM_PERIODIC_ADV_DATA_LENGTH ? QCOM_CON_MANGER_PA_FRAGMENT_TYPE_LAST :
                                                                      QCOM_CON_MANGER_PA_FRAGMENT_TYPE_INTERMEDIATE;
    }

    if (prim->adv_data_len > VSDM_PERIODIC_ADV_DATA_LENGTH)
    {
        prim->adv_data_len = VSDM_PERIODIC_ADV_DATA_LENGTH;
    }

    /* Update the PA fragment data in the array of data pointers where each index of data ptr shall hold maximum of
       VSDM_PERIODIC_ADV_DATA_BYTES_PER_PTR */
    for (offset = data_ptrs_index = 0; offset < prim->adv_data_len; offset += length, data_ptrs_index++)
    {
        length = prim->adv_data_len - offset;
        if (length > VSDM_PERIODIC_ADV_DATA_BYTES_PER_PTR)
        {
            length = VSDM_PERIODIC_ADV_DATA_BYTES_PER_PTR;
        }

        prim->adv_data[data_ptrs_index] = (uint8 *) PanicUnlessMalloc(length * sizeof(uint8));
        memcpy(prim->adv_data[data_ptrs_index],
               &pa_data_ctx->pa_data.data[pa_data_ctx->next_data_index],
               length * sizeof(uint8));
        pa_data_ctx->next_data_index += length;
    }

    DEBUG_LOG("qcomConManagerSendSetPADataReq, adv handle=%04x, operation=%d, data_fragment_length=%d",
              pa_data_ctx->pa_data.adv_handle, prim->operation, prim->adv_data_len);

    /* Send VSDM_LE_SET_PERIODIC_ADVERTISING_DATA_REQ */
    VmSendVsdmPrim(prim);
}

static void qcomConManagerResetPADataCtx(void)
{
    memset(&set_pa_data_context, 0, sizeof(set_pa_data_context));
}

static void qcomConManagerSendSetPADataCfm(hci_return_t cfm_status)
{
    MESSAGE_MAKE(set_pa_data_cfm, QCOM_CON_MANAGER_SET_PA_DATA_CFM_T);
    set_pa_data_cfm->status = cfm_status;
    TaskList_MessageSend(&QcomConManagerGet()->client_tasks, QCOM_CON_MANAGER_SET_PA_DATA_CFM, set_pa_data_cfm);
}

static void qcomConManagerSetPADataCfm(const VSDM_LE_SET_PERIODIC_ADVERTISING_DATA_CFM_T *cfm)
{
    DEBUG_LOG("qcomConManagerSetPADataCfm, status=%d, PA data size=%d, Size of PA data sent=%d",
              cfm->status, set_pa_data_context.pa_data.size, set_pa_data_context.next_data_index);
    if ((cfm->status == HCI_SUCCESS) && (set_pa_data_context.next_data_index < set_pa_data_context.pa_data.size))
    {
        /* Send next PA data fragment in case of multiple data fragments and prev fragment is sent successfully */
        qcomConManagerSendSetPADataReq(&set_pa_data_context);
    }
    else
    {
        /* Send CFM msg with HCI_SUCCESS/HCI ERROR status for setting PA data with time info */
        qcomConManagerSendSetPADataCfm(cfm->status);
        qcomConManagerResetPADataCtx();
    }
}
#endif /* INCLUDE_LE_AUDIO_BROADCAST_SOURCE */

#ifdef ENABLE_ACK_FOR_PA_TRANSMITTED
static void qcomConManagerHandleVsdmAckforPATranstimmetedInd(void)
{
    qcomConManagerTaskData *sp = QcomConManagerGet();
    /* Nothing coming from VSDM_LE_PA_DATA_TRANSMITTED_IND_T makes sense for application. All it requires is if PA got transmitted.
       So, there is no data attached to QCOM_CON_MANAGER_PA_ACK_IND message */
    TaskList_MessageSendId(&sp->client_tasks, QCOM_CON_MANAGER_PA_TRANSMITTED_ACK_IND);
}
#endif /* ENABLE_ACK_FOR_PA_TRANSMITTED */

static void qcomConManagerHandleVsdmQlmConnectionCompleteInd(const VSDM_QLM_CONNECTION_COMPLETE_IND_T *ind)
{
    bool qlmp_connected = FALSE;
    bdaddr bd_addr;

    DEBUG_LOG("qcomConManagerHandleVsdmQlmConnectionCompleteInd status=0x%x lap=%06lX",
               ind->status,ind->bd_addr.lap);

    if(ind->status == HCI_SUCCESS)
    {
        qcomConManagerTriggerRemoteFeaturesRead(&ind->bd_addr, REQUEST_REMOVE_FEATURES_DELAY_MS);
        qlmp_connected = TRUE;
    }

    BdaddrConvertBluestackToVm(&bd_addr, &ind->bd_addr);
    ConManagerSetQlmpConnectStatus(&bd_addr, qlmp_connected);
}

static void qcomConManagerHandleVsdmQllConnectionCompleteInd(const VSDM_QLL_CONNECTION_COMPLETE_IND_T *ind)
{
    DEBUG_LOG("qcomConManagerHandleVsdmQllConnectionCompleteInd status=0x%x lap=%06lX",
               ind->status, ind->tp_addrt.addrt.addr.lap);

    /* QLL got connected. Trigger a remote feature read request */
    if (ind->status == HCI_SUCCESS)
    {
        qcomConManagerQllTriggerRemoteFeaturesRead(&ind->tp_addrt, D_IMMEDIATE);
    }
}

static void qcomConManagerHandleVsdmScHostSuppOverrideCfm(const VSDM_WRITE_SC_HOST_SUPP_OVERRIDE_CFM_T *cfm)
{
    PanicFalse(cfm->status == HCI_SUCCESS);
}

static void qcomConManagerSendScHostSuppOverrideReq(void)
{
    uint8 count =0;

    MAKE_VSDM_PRIM_T(VSDM_WRITE_SC_HOST_SUPP_OVERRIDE_REQ);
    prim->phandle = 0;
    prim->num_compIDs = count;

    while(vendor_info[count].comp_id != 0)
    {
        prim->compID[count] = vendor_info[count].comp_id;
        prim->min_lmpVersion[count] = vendor_info[count].min_lmp_version;
        prim->min_lmpSubVersion[count] = vendor_info[count].min_lmp_sub_version;
        prim->num_compIDs = ++count;

        /* Check if input number of comp ids are not exceeding
           maximum number of comp ids supported by vs prims */
        if(prim->num_compIDs == VSDM_MAX_NO_OF_COMPIDS)
        {
            Panic();
        }
    }

    if(prim->num_compIDs != 0)
    {
        VmSendVsdmPrim(prim);
    }

    /* Send init confirmation */
    MessageSend(SystemState_GetTransitionTask(), QCOM_CON_MANAGER_INIT_CFM, NULL);
}

static void qcomConManagerSetLocalSupportedFeaturesFlags(const uint8 *features)
{
    /* Check if qhs is supported or not */
    if (qcomConManagerIsQhsSupported(features))
    {
        QcomConManagerGet()->qhs = TRUE;
    }
    if (qcomConManagerIsFastExitSubrateSupported(features))
    {
        QcomConManagerGet()->fast_exit_sniff_subrate = TRUE;
    }
}

static void qcomConManagerHandleVsdmLocalQlmSuppFeaturesCfm(const VSDM_READ_LOCAL_QLM_SUPP_FEATURES_CFM_T *cfm)
{
    PanicFalse(cfm->status == HCI_SUCCESS);

    qcomConManagerSetLocalSupportedFeaturesFlags(cfm->qlmp_supp_features);

    if (QcomConManagerGet()->qhs)
    {
        /* Send SC host override req as local device supports qhs*/
        qcomConManagerSendScHostSuppOverrideReq();
    }
    else
    {
        DEBUG_LOG("qcomConManagerHandleVsdmLocalQlmSuppFeaturesCfm: QHS not supported");
        /* Inform application that qcom con manager init completed */
        MessageSend(SystemState_GetTransitionTask(), QCOM_CON_MANAGER_INIT_CFM, NULL);
    }
}


static void qcomConManagerSendReadLocalQlmSuppFeaturesReq(void)
{
    /*send VSDM_READ_LOCAL_QLM_SUPP_FEATURES_REQ  to find if qhs is supported or not*/
    MAKE_VSDM_PRIM_T(VSDM_READ_LOCAL_QLM_SUPP_FEATURES_REQ);
    prim->phandle = 0;
    VmSendVsdmPrim(prim);
}

#if defined(INCLUDE_LE_AUDIO_UNICAST) || defined(INCLUDE_LE_AUDIO_BROADCAST)
static void qcomConnManagerSendWriteScHostSuppCodOverrideReq(uint8_t bit_number, bool enable)
{
    /*send VSDM_WRITE_SC_HOST_SUPP_COD_OVERRIDE_REQ */
    MAKE_VSDM_PRIM_T(VSDM_WRITE_SC_HOST_SUPP_COD_OVERRIDE_REQ);

    prim->phandle = 0;
    prim->bit_number = bit_number;
    prim->enable = enable;
    VmSendVsdmPrim(prim);
}
#endif

#ifdef ENABLE_ACK_FOR_PA_TRANSMITTED
static void qcomConnManagerSetEventMaskToEnableAckForPATransmittedReq(void)
{
    MAKE_VSDM_PRIM_T(VSDM_SET_EVENT_MASK_REQ);

    prim->phandle = 0;
    prim->evt_mask_type = VSDM_EVT_TYPE_QLL;
    memset(&prim->evt_mask[0], 0, VSDM_SIZE_OF_EVT_MASK);
    prim->evt_mask[QLL_PA_TRANSMITTED_EVENT_OCTET] |= (1 << QLL_PA_TRANSMITTED_BIT_OFFSET);
    VmSendVsdmPrim(prim);
}
#endif /*ENABLE_ACK_FOR_PA_TRANSMITTED */


static void qcomConManagerHandleVsdmRegisterCfm(const VSDM_REGISTER_CFM_T *cfm)
{
    PanicFalse(cfm->result == VSDM_RESULT_SUCCESS);
    /*Check if local device supports qhs or not and proceed to create qhs with remote
      handset if local supports qhs */
    qcomConManagerSendReadLocalQlmSuppFeaturesReq();

#if defined(INCLUDE_LE_AUDIO_UNICAST) || defined(INCLUDE_LE_AUDIO_BROADCAST)
    qcomConnManagerSendWriteScHostSuppCodOverrideReq(LE_AUDIO_MAJOR_SERV_CLASS_BIT_POS, TRUE);
#endif

#ifdef ENABLE_ACK_FOR_PA_TRANSMITTED
    qcomConnManagerSetEventMaskToEnableAckForPATransmittedReq();
#endif
}

static void qcomConManagerRegisterReq(void)
{
    MAKE_VSDM_PRIM_T(VSDM_REGISTER_REQ);
    prim->phandle = 0;
    VmSendVsdmPrim(prim);
}

static task_list_t* qcomConManagerGetBargeInClientTasks(void)
{
    return &QcomConManagerGet()->barge_in_client_tasks;
}

/*! \brief Send BREDR barge in indication */
static void qcomConManagerSendBargeInInd(bdaddr * addr)
{
    DEBUG_LOG_INFO("qcomConManagerSendBargeInInd lap=0x%x", addr->lap);
    MESSAGE_MAKE(ind, QCOM_CON_MANAGER_BARGE_IN_IND_T);
    ind->bd_addr.uap = addr->uap;
    ind->bd_addr.lap = addr->lap;
    ind->bd_addr.nap = addr->nap;

    TaskList_MessageSend(qcomConManagerGetBargeInClientTasks(), QCOM_CON_MANAGER_BARGE_IN_IND, ind);
}

static void qcomConManagerHandleVsdmIncomingPageInd(const VSDM_INCOMING_PAGE_IND_T *ind)
{
    DEBUG_LOG("qcomConManagerHandleVsdmIncomingPageInd");
    bdaddr bd_addr;
    tp_bdaddr tpaddr;

    BdaddrConvertBluestackToVm(&bd_addr, &ind->bd_addr);
    BdaddrTpFromBredrBdaddr(&tpaddr, &bd_addr);
    ConManager_EventSendAclBargeInRequest(&tpaddr);
    qcomConManagerSendBargeInInd(&bd_addr);
}

static void qcomConManagerHandleVsdmTruncatedPageScanEnableCfm(const VSDM_WRITE_TRUNCATED_PAGE_SCAN_ENABLE_CFM_T *cfm)
{
    DEBUG_LOG("qcomConManagerHandleVsdmTruncatedPageScanEnableCfm status:0x%x", cfm->status);
    MESSAGE_MAKE(msg, QCOM_CON_MANAGER_TRUNCATED_SCAN_ENABLE_CFM_T);
    msg->status = cfm->status;

    MessageSend(client_truncated_scan, QCOM_CON_MANAGER_TRUNCATED_SCAN_ENABLE_CFM, msg);
}

static void qcomConManagerHandleVsdmSetStreamingModeCfm(const VSDM_SET_STREAMING_MODE_CFM_T *cfm)
{
    DEBUG_LOG("qcomConManagerHandleVsdmSetStreamingModeCfm status:0x%x", cfm->status);
}

#ifdef INCLUDE_LE_APTX_ADAPTIVE
#ifdef INCLUDE_LE_AUDIO_UNICAST_SOURCE
static void qcomConManagerHandleVsdmQhsRateChangedInd(const VSDM_CIG_QHS_RATE_CHANGED_IND_T *ind)
{
    qcomConManagerTaskData *sp = QcomConManagerGet();

    DEBUG_LOG("qcomConManagerHandleVsdmQhsRateChangedInd");

    MESSAGE_MAKE(msg, QCOM_CON_MANAGER_QHS_RATE_CHANGED_IND_T);
    msg->cig_id = ind->cig_id;
    msg->qhs_rate = ind->qhs_rate;
    TaskList_MessageSend(&sp->client_tasks, QCOM_CON_MANAGER_QHS_RATE_CHANGED_IND, msg);
}
#endif
#endif

#ifdef ENABLE_LE_CONNECTION_BARGE_IN
/*! \brief Send VSDM command to accept the LE barge in from given device */
static void qcomConManagerSendVsdmLeAcceptBargeIn(hci_connection_handle_t con_handle)
{
    MAKE_VSDM_PRIM_T(VSDM_LE_ACCEPT_CONNECTION_REQ);
    prim->phandle = 0x0;
    prim->con_handle = con_handle;
    VmSendVsdmPrim(prim);
}

/*! \brief Send VSDM command to reject the LE barge in from given device */
static void qcomConManagerSendVsdmLeRejectBargeIn(hci_connection_handle_t con_handle, hci_error_t reason)
{
    MAKE_VSDM_PRIM_T(VSDM_LE_REJECT_CONNECTION_REQ);
    prim->phandle = 0x0;
    prim->con_handle = con_handle;
    prim->reason = reason;
    VmSendVsdmPrim(prim);
}

/*! \brief Reset the entries for LE barge in */
static void qcomConManagerResetLeBargeInEntry(void)
{
    qcomConManagerBargeInList *connection;

    for(connection = &qcom_con_manager.le_barge_in_connections[0];
        connection <= &qcom_con_manager.le_barge_in_connections[QCOM_CON_MANAGER_GATT_LE_BARGE_IN_CONNECTIONS - 1]; connection++)
    {
        BdaddrTypedSetEmpty(&connection->barge_in_addr);
    }
}

/*! \brief Find an entry from LE barge-in list matching with the given address */
static qcomConManagerBargeInList* qcomConManagerFindLeBargeInEntry(typed_bdaddr *barge_in_addr)
{
    qcomConManagerBargeInList *connection;

    for (connection = &QcomConManagerGet()->le_barge_in_connections[0];
         connection <= &QcomConManagerGet()->le_barge_in_connections[QCOM_CON_MANAGER_GATT_LE_BARGE_IN_CONNECTIONS - 1]; connection++)
    {
        if (BdaddrTypedIsSame(&connection->barge_in_addr, barge_in_addr))
        {
            return connection;
        }
    }

    return NULL;
}

/*! \brief Add the given address to LE barge in list */
static bool qcomConManagerAddLeBargeInEntry(typed_bdaddr *barge_in_address, uint16_t conn_handle)
{
    bool status = FALSE;
    typed_bdaddr empty_address;
    qcomConManagerBargeInList *connection;

    BdaddrTypedSetEmpty(&empty_address);
    connection = qcomConManagerFindLeBargeInEntry(&empty_address);

    if (connection != NULL)
    {
        status = TRUE;
        connection->barge_in_addr = *barge_in_address;
        connection->conn_handle = conn_handle;
    }
    else
    {
        /* There is no free slot available */
        DEBUG_LOG("qcomConManagerAddLeBargeInEntry error");
    }

    return status;
}

/*! \brief Remove the given address from LE barge in list */
static void qcomConManagerRemoveLeBargeInEntry(qcomConManagerBargeInList *connection)
{
    if (connection != NULL)
    {
        memset(connection, 0, sizeof(qcomConManagerBargeInList));
        BdaddrTypedSetEmpty(&connection->barge_in_addr);
    }
}

/*! \brief Handle incoming LE barge in indication */
static void qcomConManagerHandleVsdmLeBargeInInd(const VSDM_ENHANCED_INCOMING_LE_CONNECTION_IND_T *ind)
{
    tp_bdaddr barge_in_address = {.transport =  TRANSPORT_BLE_ACL};

    DEBUG_LOG_INFO("qcomConManagerHandleVsdmLeBargeInInd lap=0x%x type=%d con_hdl=0x%x adv_hdl=0x%x",
                   ind->peer_addr.addr.lap, ind->peer_addr.type, ind->con_handle, ind->adv_handle);

    BdaddrConvertTypedBluestackToVm(&barge_in_address.taddr, &ind->peer_addr);

    /* If it is peer device which connects over truncated advertisement(i.e, barges in), then auto accept it. */
    if (BtDevice_LeDeviceIsPeer(&barge_in_address))
    {
        DEBUG_LOG_INFO("qcomConManagerHandleVsdmLeBargeInInd auto accept as peer");

        qcomConManagerSendVsdmLeAcceptBargeIn(ind->con_handle);
        return;
    }

    if (qcomConManagerAddLeBargeInEntry(&barge_in_address.taddr, ind->con_handle))
    {
        /* Send QCOM_CON_MANAGER_LE_BARGE_IN_IND to registered barge in client */
        MESSAGE_MAKE(msg, QCOM_CON_MANAGER_LE_BARGE_IN_IND_T);
        msg->barge_in_address = barge_in_address.taddr;
        TaskList_MessageSend(qcomConManagerGetBargeInClientTasks(), QCOM_CON_MANAGER_LE_BARGE_IN_IND, msg);
    }
    else
    {
        /* Auto reject the barge in as we have received more barge in indications than we are capable to handle.*/
        DEBUG_LOG_ERROR("qcomConManagerHandleVsdmLeBargeInInd rejecting as another barge-in is in progress");

        qcomConManagerSendVsdmLeRejectBargeIn(ind->con_handle, hci_error_oetc_user);
    }
}

/*! \brief Handle LE barge in accept connection confirmation */
static void qcomConManagerHandleVsdmBargeInLeAcceptCfm(const VSDM_LE_ACCEPT_CONNECTION_CFM_T *cfm)
{
    DEBUG_LOG_INFO("qcomConManagerHandleVsdmBargeInLeAcceptCfm status=%d", cfm->status);
}

/*! \brief Handle LE barge in reject connection confirmation */
static void qcomConManagerHandleVsdmBargeInLeRejectCfm(const VSDM_LE_REJECT_CONNECTION_CFM_T *cfm)
{
    DEBUG_LOG_INFO("qcomConManagerHandleVsdmBargeInLeRejectCfm status=%d", cfm->status);
}
#endif /* ENABLE_LE_CONNECTION_BARGE_IN */

static void qcomConManagerHandleVsdmLowerConnectionPriorityCfm(const VSDM_LOWER_CONNECTION_PRIORITY_CFM_T* cfm)
{
    DEBUG_LOG_INFO("qcomConManagerHandleVsdmLowerConnectionPriorityCfm 0x%x 0x%x", cfm->phandle, cfm->status);
}

#ifdef INCLUDE_ACCESSORY_DEVICE_SERVICE

static void qcomConManagerHandleLowerConnectionPriorityCfmForAccessoryDevice(const VSDM_LINK_TYPE_PRIORITY_CFM_T* cfm)
{
    DEBUG_LOG_INFO("qcomConManagerHandleLowerConnectionPriorityCfmForAccessoryDevice status 0x%x", cfm->status);
}

#endif /* INCLUDE_ACCESSORY_DEVICE_SERVICE */

static void qcomConManagerHandleBluestackVsdmPrim(const VSDM_UPRIM_T *vsprim)
{
    switch (vsprim->type)
    {
    case VSDM_REGISTER_CFM:
        qcomConManagerHandleVsdmRegisterCfm((const VSDM_REGISTER_CFM_T *)vsprim);
        break;
    case VSDM_READ_LOCAL_QLM_SUPP_FEATURES_CFM:
        qcomConManagerHandleVsdmLocalQlmSuppFeaturesCfm((VSDM_READ_LOCAL_QLM_SUPP_FEATURES_CFM_T *)vsprim);
        break;
    case VSDM_WRITE_SC_HOST_SUPP_OVERRIDE_CFM:
        qcomConManagerHandleVsdmScHostSuppOverrideCfm((const VSDM_WRITE_SC_HOST_SUPP_OVERRIDE_CFM_T *)vsprim);
        break;
     case VSDM_QLM_CONNECTION_COMPLETE_IND:
        qcomConManagerHandleVsdmQlmConnectionCompleteInd((const VSDM_QLM_CONNECTION_COMPLETE_IND_T *)vsprim);
        break;
    case VSDM_READ_REMOTE_QLM_SUPP_FEATURES_CFM:
       qcomConManagerHandleVsdmRemoteQlmSuppFeaturesCfm((const VSDM_READ_REMOTE_QLM_SUPP_FEATURES_CFM_T *)vsprim);
       break;
    case VSDM_QCM_PHY_CHANGE_IND:
        qcomConManagerHandleVsdmQlmPhyChangeInd((const VSDM_QCM_PHY_CHANGE_IND_T *)vsprim);
        break;
    case VSDM_SET_WBM_FEATURES_CFM:
        qcomConManagerHandleVsdmSetWbmFeatureCfm((const VSDM_SET_WBM_FEATURES_CFM_T *)vsprim);
        break;

    case VSDM_INCOMING_PAGE_IND:
        qcomConManagerHandleVsdmIncomingPageInd((const VSDM_INCOMING_PAGE_IND_T *)vsprim);
        break;

    case VSDM_WRITE_TRUNCATED_PAGE_SCAN_ENABLE_CFM:
        qcomConManagerHandleVsdmTruncatedPageScanEnableCfm((const VSDM_WRITE_TRUNCATED_PAGE_SCAN_ENABLE_CFM_T *)vsprim);
        break;
    case VSDM_SET_STREAMING_MODE_CFM:
        qcomConManagerHandleVsdmSetStreamingModeCfm((const VSDM_SET_STREAMING_MODE_CFM_T*)vsprim);
        break;
    case VSDM_QLL_CONNECTION_COMPLETE_IND:
        qcomConManagerHandleVsdmQllConnectionCompleteInd((const VSDM_QLL_CONNECTION_COMPLETE_IND_T *)vsprim);
        break;
    case VSDM_READ_REMOTE_QLL_SUPP_FEATURES_CFM:
        qcomConManagerHandleVsdmRemoteQllSuppFeaturesCfm((const VSDM_READ_REMOTE_QLL_SUPP_FEATURES_CFM_T *)vsprim);
        break;
#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE
    case VSDM_LE_SET_PERIODIC_ADVERTISING_DATA_CFM:
        qcomConManagerSetPADataCfm((const VSDM_LE_SET_PERIODIC_ADVERTISING_DATA_CFM_T *)vsprim);
#endif /* INCLUDE_LE_AUDIO_BROADCAST_SOURCE */

#ifdef INCLUDE_LE_APTX_ADAPTIVE
#ifdef INCLUDE_LE_AUDIO_UNICAST_SOURCE
    case VSDM_QLE_SET_CIG_QHS_MAP_CFM:
        DEBUG_LOG("qcomConManagerHandleBluestackVsdmPrim : VSDM_QLE_SET_CIG_QHS_MAP_CFM status %x", ((VSDM_QLE_SET_CIG_QHS_MAP_CFM_T*) vsprim)->status);
        break;

    case VSDM_CIG_QHS_RATE_CHANGED_IND:
        qcomConManagerHandleVsdmQhsRateChangedInd((const VSDM_CIG_QHS_RATE_CHANGED_IND_T *)vsprim);
        break;
#endif
#endif

#if defined(INCLUDE_LE_AUDIO_UNICAST) || defined(INCLUDE_LE_AUDIO_BROADCAST)
    case VSDM_WRITE_SC_HOST_SUPP_COD_OVERRIDE_CFM:
        DEBUG_LOG("qcomConManagerHandleBluestackVsdmPrim : VSDM_WRITE_SC_HOST_SUPP_COD_OVERRIDE_CFM status %x", ((VSDM_WRITE_SC_HOST_SUPP_COD_OVERRIDE_CFM_T*) vsprim)->status);
        break;
#endif

#ifdef ENABLE_ACK_FOR_PA_TRANSMITTED
    case VSDM_SET_EVENT_MASK_CFM:
        DEBUG_LOG("qcomConManagerHandleBluestackVsdmPrim : VSDM_SET_EVENT_MASK_CFM result %x", ((VSDM_SET_EVENT_MASK_CFM_T*) vsprim)->result);
        break;

    case VSDM_LE_PA_DATA_TRANSMITTED_IND:
        qcomConManagerHandleVsdmAckforPATranstimmetedInd();
        break;
#endif /* ENABLE_ACK_FOR_PA_TRANSMITTED */


#ifdef ENABLE_LE_CONNECTION_BARGE_IN
    case VSDM_ENHANCED_INCOMING_LE_CONNECTION_IND:
        qcomConManagerHandleVsdmLeBargeInInd((const VSDM_ENHANCED_INCOMING_LE_CONNECTION_IND_T*)vsprim);
        break;

    case VSDM_LE_ACCEPT_CONNECTION_CFM:
        qcomConManagerHandleVsdmBargeInLeAcceptCfm((const VSDM_LE_ACCEPT_CONNECTION_CFM_T*)vsprim);
        break;

    case VSDM_LE_REJECT_CONNECTION_CFM:
        qcomConManagerHandleVsdmBargeInLeRejectCfm((const VSDM_LE_REJECT_CONNECTION_CFM_T*)vsprim);
        break;
#endif /* ENABLE_LE_CONNECTION_BARGE_IN */

    case VSDM_LOWER_CONNECTION_PRIORITY_CFM:
        qcomConManagerHandleVsdmLowerConnectionPriorityCfm((const VSDM_LOWER_CONNECTION_PRIORITY_CFM_T*)vsprim);
        break;

#ifdef INCLUDE_ACCESSORY_DEVICE_SERVICE
    case VSDM_LINK_TYPE_PRIORITY_CFM :
        qcomConManagerHandleLowerConnectionPriorityCfmForAccessoryDevice((const VSDM_LINK_TYPE_PRIORITY_CFM_T*)vsprim);
        break;
#endif /* INCLUDE_ACCESSORY_DEVICE_SERVICE */

    default:
        DEBUG_LOG("qcomConManagerHandleBluestackVsdmPrim : unhandled vsprim type %x", vsprim->type);
        if (vsdm_prim_observer)
        {
            vsdm_prim_observer(vsprim);
        }
        break;
    }
}

static void qcomConManagerHandleMessage(Task task, MessageId id, Message message)
{
   UNUSED(task);

   switch (id)
   {
     /* VSDM prims from firmware */
    case MESSAGE_BLUESTACK_VSDM_PRIM:
        qcomConManagerHandleBluestackVsdmPrim((const VSDM_UPRIM_T *)message);
        break;

    case QCOM_CON_MANAGER_INTERNAL_READ_QLM_REMOTE_FEATURES:
    {
        const QCOM_CON_MANAGER_INTERNAL_READ_QLM_REMOTE_FEATURES_T *msg = message;
        qcomConManagerSendReadRemoteQlmSuppFeaturesReq(&msg->bd_addr);
        break;
    }

    case QCOM_CON_MANAGER_INTERNAL_READ_QLL_REMOTE_FEATURES:
    {
        const QCOM_CON_MANAGER_INTERNAL_READ_QLL_REMOTE_FEATURES_T *msg = message;
        qcomConManagerSendReadRemoteQllSuppFeaturesReq(&msg->tp_addr);
        break;
    }

    default:
        break;
    }
}
/* Global functions */

bool QcomConManagerInit(Task task)
{
    UNUSED(task);

    DEBUG_LOG("QcomConManagerInit");
    memset(&qcom_con_manager, 0, sizeof(qcom_con_manager));

#ifdef ENABLE_LE_CONNECTION_BARGE_IN
    qcomConManagerResetLeBargeInEntry();
#endif /* ENABLE_LE_CONNECTION_BARGE_IN */

    qcom_con_manager.task.handler = qcomConManagerHandleMessage;
    TaskList_Initialise(&qcom_con_manager.client_tasks);
    TaskList_Initialise(qcomConManagerGetBargeInClientTasks());

    /* Register with the firmware to receive MESSAGE_BLUESTACK_VSDM_PRIM messages */
    MessageVsdmTask(QcomConManagerGetTask());

    /* Register with the VSDM service */
    qcomConManagerRegisterReq();

    return TRUE;
}

void QcomConManagerRegisterClient(Task client_task)
{
    DEBUG_LOG("QcomConManagerRegisterClient");
    TaskList_AddTask(&qcom_con_manager.client_tasks, client_task);
}

void QcomConManagerUnRegisterClient(Task client_task)
{
    TaskList_RemoveTask(&qcom_con_manager.client_tasks, client_task);
}

bool QcomConManagerIsFastExitSniffSubrateSupported(const bdaddr *addr)
{
    return QcomConManagerGet()->fast_exit_sniff_subrate &&
           ConManagerGetFastExitSniffSubrateSupportStatus(addr);
}

#ifdef ENABLE_LE_AUDIO_WBM
void QcomConManagerSetWBMFeature(hci_connection_handle_t conn_handle, bool enable)
{
    DEBUG_LOG("QcomConManagerSetWBMFeature, handle 0x%x, Enable %d", conn_handle, enable);

    /* send VSDM_SET_WBM_FEATURES_REQ to SET WBM ENABLE_BIT MASK */
    MAKE_VSDM_PRIM_T(VSDM_SET_WBM_FEATURES_REQ);
    prim->phandle = 0;
    prim->enable_mask = enable ? WBM_FEATURES_BIT_ENABLE : WBM_FEATURES_BIT_DISABLE;
    prim->conn_handle = conn_handle;
    VmSendVsdmPrim(prim);
}
#endif

void QcomConManagerSetStreamingMode(tp_bdaddr *tp_addr, uint8_t streaming_mode)
{
    DEBUG_LOG("QcomConManagerSetStreamingMode, mode %d", streaming_mode);

    MAKE_VSDM_PRIM_T(VSDM_SET_STREAMING_MODE_REQ);
    prim->phandle = 0x0;  /* Destination phandle */
    /* Address of the remote device */
    prim->tp_addrt.tp_type = (PHYSICAL_TRANSPORT_T)tp_addr->transport;
    prim->tp_addrt.addrt.type = tp_addr->taddr.type;
    prim->tp_addrt.addrt.addr.lap = tp_addr->taddr.addr.lap;
    prim->tp_addrt.addrt.addr.nap = tp_addr->taddr.addr.nap;
    prim->tp_addrt.addrt.addr.uap = tp_addr->taddr.addr.uap;

    prim->streaming_mode = streaming_mode; /* Streaming mode to be set */
    VmSendVsdmPrim(prim);
}

void QcomConManagerEnableTruncatedScan(Task client_task, bool enable)
{
    DEBUG_LOG("QcomConManagerEnableTruncatedScan, enable %d", enable);

    MAKE_VSDM_PRIM_T(VSDM_WRITE_TRUNCATED_PAGE_SCAN_ENABLE_REQ);
    prim->phandle = 0x0;
    prim->enable = enable ? WRITE_TRUNCATED_PAGE_SCAN_ENABLE : WRITE_TRUNCATED_PAGE_SCAN_DISABLE;
    VmSendVsdmPrim(prim);
    client_truncated_scan = client_task;
}

void QcomConManagerSetFlushTimeoutRange(const QCOM_CON_MANAGER_SET_FLUSH_TIMEOUT_RANGE_PARAM_T *flush_timeout_req)
{
    DEBUG_LOG("QcomConManagerSetFlushTimeoutRange, CIG ID 0x%x, FT Enable %d", flush_timeout_req->cig_id, flush_timeout_req->enable);

    /* send VSDM_QLE_SET_FLUSH_TIMEOUT_RANGE_REQ */
    MAKE_VSDM_PRIM_T(VSDM_QLE_SET_FLUSH_TIMEOUT_RANGE_REQ);
    prim->phandle = 0;
    prim->cig_id = flush_timeout_req->cig_id;
    prim->enable = flush_timeout_req->enable;
    prim->ll_mode = flush_timeout_req->ll_mode;
    prim->min_ft_c_to_p = flush_timeout_req->min_ft_c_to_p;
    prim->max_ft_c_to_p = flush_timeout_req->max_ft_c_to_p;
    prim->min_ft_p_to_c = flush_timeout_req->min_ft_p_to_c;
    prim->max_ft_p_to_c = flush_timeout_req->max_ft_p_to_c;
    prim->ttp_adjust_rate = flush_timeout_req->ttp_adjust_rate;
    VmSendVsdmPrim(prim);
}

#ifdef INCLUDE_LE_APTX_ADAPTIVE
#ifdef INCLUDE_LE_AUDIO_UNICAST_SOURCE
COMPILE_TIME_ASSERT(QCOM_MAX_SUPPORTED_CIS <= VSDM_MAX_SUPPORTED_CIS, supported_cis_mismatch);
COMPILE_TIME_ASSERT(QCOM_MAX_NUM_OF_QHS_RATE <= VSDM_MAX_NUM_OF_QHS_RATE, no_of_qhs_map_mismatch);

void QcomConManagerSetQHSMapReq(const QCOM_CON_MANAGER_SET_CIG_QHS_MAP_REQ_T *qhs_map_req)
{
    uint8 i, cis_id;

    /* send VSDM_QLE_SET_CIG_QHS_MAP_REQ */
    MAKE_VSDM_PRIM_T(VSDM_QLE_SET_CIG_QHS_MAP_REQ);
    prim->phandle = 0;
    prim->cig_id = qhs_map_req->cig_id;
    prim->flags = qhs_map_req->flags;
    prim->cis_count = qhs_map_req->cis_count;
    prim->cis_qhs_map[0].cis_id = qhs_map_req->cis_ids[0];
    prim->cis_qhs_map[1].cis_id = qhs_map_req->cis_ids[1];

    DEBUG_LOG("QcomConManagerSetQHSMapReq, CIG ID 0x%x", qhs_map_req->cig_id);
    for (cis_id = 0 ; cis_id < QCOM_MAX_SUPPORTED_CIS; cis_id++)
    {
        DEBUG_LOG(" QHS Map for CIS ID %d", cis_id);

        memcpy(prim->cis_qhs_map[cis_id].cis_params_qhs,
               qhs_map_req->cis_qhs_map,
               QCOM_MAX_NUM_OF_QHS_RATE * sizeof(QCOM_CON_MANAGER_CIS_QHS_PARAMS_T));

        for(i = 0; i < QCOM_MAX_NUM_OF_QHS_RATE; i++)
        {
            DEBUG_LOG("QHS[%d] bn_c_to_p = %d, bn_p_to_c = %d, max_pdu_c_to_p = %d ,max_pdu_p_to_c %d",
                      i,prim->cis_qhs_map[cis_id].cis_params_qhs[i].bn_c_to_p,
                      prim->cis_qhs_map[cis_id].cis_params_qhs[i].bn_p_to_c,
                      prim->cis_qhs_map[cis_id].cis_params_qhs[i].max_pdu_c_to_p,
                      prim->cis_qhs_map[cis_id].cis_params_qhs[i].max_pdu_p_to_c);
        }
    }

    VmSendVsdmPrim(prim);
}
#endif
#endif /* INCLUDE_LE_APTX_ADAPTIVE */

void QcomConManagerRegisterBargeInClient(Task client_task)
{
    TaskList_AddTask(qcomConManagerGetBargeInClientTasks(), client_task);
}

void QcomConManagerRegisterVsdmPrimObserver(QcomConManagerVsdmPrimObserver observer)
{
    if (vsdm_prim_observer && (vsdm_prim_observer != observer))
    {
        DEBUG_LOG_PANIC("QcomConManagerRegisterVsdmPrimObserver: Currently only one observer is supported");
    }
    vsdm_prim_observer = observer;
}

#ifdef ENABLE_LE_CONNECTION_BARGE_IN
bool QcomConManagerAcceptLeBargeInConnection(typed_bdaddr *barge_in_address)
{
    bool status = FALSE;
    qcomConManagerBargeInList *connection = qcomConManagerFindLeBargeInEntry(barge_in_address);

    DEBUG_LOG_INFO("QcomConManagerAcceptLeBargeInConnection lap:0x%x connection %p", barge_in_address->addr.lap, connection);

    if (connection != NULL)
    {
        /* Send the request and remove the barge in entry from the list */
        qcomConManagerSendVsdmLeAcceptBargeIn(connection->conn_handle);
        qcomConManagerRemoveLeBargeInEntry(connection);

        status = TRUE;
    }

    return status;
}

bool QcomConManagerRejectLeBargeInConnection(typed_bdaddr *barge_in_address, uint8_t reason)
{
    bool status = FALSE;
    qcomConManagerBargeInList *connection = qcomConManagerFindLeBargeInEntry(barge_in_address);

    DEBUG_LOG_INFO("QcomConManagerRejectLeBargeInConnection lap:0x%x connection 0x%p reason 0x%x", barge_in_address->addr.lap, connection, reason);

    if (connection != NULL)
    {
        /* Send the request and remove the barge in entry from the list */
        qcomConManagerSendVsdmLeRejectBargeIn(connection->conn_handle, reason);
        qcomConManagerRemoveLeBargeInEntry(connection);

        status = TRUE;
    }

    return status;
}
#endif /* ENABLE_LE_CONNECTION_BARGE_IN */

#ifdef INCLUDE_LE_AUDIO_BROADCAST_SOURCE
void QcomConManagerSetPADataReq(uint8 adv_handle,
                                uint8 *adv_data,
                                uint16 adv_data_length,
                                uint32 anchor_point_us,
                                uint16 time_to_sync_point_ms,
                                uint16 offset_for_time_info)
{
    DEBUG_LOG("QcomConManagerSetPADataReq, adv_handle %d, adv_data_length %d, anchor_point_us = %d,"
              "time_to_sync_point_ms %d, offset_for_time_info %d early_req_pending: %d", adv_handle, adv_data_length,
              anchor_point_us, time_to_sync_point_ms, offset_for_time_info, set_pa_data_context.pa_data.data != NULL);

    /* Process the Set PA data req only if previous req is completed, else send the error msg */
    if (set_pa_data_context.pa_data.data == NULL)
    {
        set_pa_data_context.next_data_index = 0;
        set_pa_data_context.pa_data.adv_handle = adv_handle;
        set_pa_data_context.pa_data.data = adv_data;
        set_pa_data_context.pa_data.size = adv_data_length;
        set_pa_data_context.pa_data.anchor_point_us = anchor_point_us;
        set_pa_data_context.pa_data.time_to_sync_point_ms = time_to_sync_point_ms;
        set_pa_data_context.pa_data.offset_for_time_info = offset_for_time_info;
        qcomConManagerSendSetPADataReq(&set_pa_data_context);
    }
    else
    {
        qcomConManagerSendSetPADataCfm(HCI_ERROR_ILLEGAL_COMMAND);
    }
}
#endif /* INCLUDE_LE_AUDIO_BROADCAST_SOURCE */

void QcomConManagerLowerConnectionPriority(tp_bdaddr tp_addr, hci_connection_handle_t conn_handle, uint8 link_type, bool lower_prio_enable)
{
    MAKE_VSDM_PRIM_T(VSDM_LOWER_CONNECTION_PRIORITY_REQ);
    prim->phandle = 0;
    prim->lower_priority = lower_prio_enable;
    prim->link_type = link_type;
    prim->conn_handle = conn_handle;
    BdaddrConvertTpVmToBluestack(&prim->tp_addrt, &tp_addr);

    DEBUG_LOG("QcomConManagerLowerConnectionPriority enable %d conn_handle 0x%x link_type 0x%x addr %04x,%02x,%06lx", 
               lower_prio_enable, conn_handle, link_type, tp_addr.taddr.addr.nap, tp_addr.taddr.addr.uap, tp_addr.taddr.addr.lap);

    VmSendVsdmPrim(prim);
}

void QcomConManagerControlLinkTypePriorityReq(tp_bdaddr *tp_addr, bool lower_prio_enable)
{
#ifdef INCLUDE_ACCESSORY_DEVICE_SERVICE

    MAKE_VSDM_PRIM_T(VSDM_LINK_TYPE_PRIORITY_REQ);

    prim->phandle = 0;
    prim->num_connections = 1;
    BdaddrConvertTpVmToBluestack(&prim->priority_list[0].tp_addrt, tp_addr);

    /* Link type is set as control connection type */
    prim->priority_list[0].link_type_mask = VSDM_LINK_TYPE_MASK_ACL_CONTROL;
    prim->priority_list[0].priority_level = lower_prio_enable ? QCOM_CON_MANGER_CONTROL_CONNECTION_PRIORITY_LOW
                                                              : QCOM_CON_MANGER_CONTROL_CONNECTION_PRIORITY_HIGH;

    DEBUG_LOG("QcomConManagerLowerConnectionPriorityForAccessoryDevice enable %d addr %04x,%02x,%06lx", 
               lower_prio_enable, tp_addr->taddr.addr.nap, tp_addr->taddr.addr.uap, tp_addr->taddr.addr.lap);

    VmSendVsdmPrim(prim);

#else /* INCLUDE_ACCESSORY_DEVICE_SERVICE */

    UNUSED(tp_addr);
    UNUSED(lower_prio_enable);

#endif /* INCLUDE_ACCESSORY_DEVICE_SERVICE */
}

#endif /* INCLUDE_QCOM_CON_MANAGER */
